package cn.xeblog.plugin.tools.read.ui;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.xeblog.plugin.cache.DataCache;
import cn.xeblog.plugin.tools.read.api.LegadoApi;
import cn.xeblog.plugin.tools.read.entity.Book;
import cn.xeblog.plugin.tools.read.entity.BookType;
import cn.xeblog.plugin.tools.read.entity.Chapter;
import cn.xeblog.plugin.tools.read.entity.LegadoBook;
import cn.xeblog.plugin.tools.read.error.LegadoApiException;
import cn.xeblog.plugin.tools.read.util.TableDataUtil;
import cn.xeblog.plugin.util.AlertMessagesUtil;
import cn.xeblog.plugin.util.CharsetUtils;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBLoadingPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * 添加书籍对话框
 *
 * @author LYF
 * @date 2022-07-19
 */
public class AddBookDialog extends JDialog {

    /**
     * 默认章节匹配正则
     */
    private static final String DEFAULT_CHAPTER_PATTERN = "^.?第(.{1,5})[章部集卷节篇回].{0,24}";

    /**
     * 主面板
     */
    private JPanel mainPanel;
    /**
     * 带加载的目录面板
     */
    private JBLoadingPanel directoryCard;
    /**
     * 带加载的legado书架面板
     */
    private JBLoadingPanel legadoBookAddCard;
    /**
     * 书籍目录
     */
    private JBList<Chapter> chapterList;
    /**
     * 书籍章节
     */
    private List<Chapter> chapters = new ArrayList<>();
    /**
     * Legado书架
     */
    private JBTable bookTable;
    /**
     * Legado API
     */
    private LegadoApi api;
    /**
     * Legado书籍
     */
    private List<LegadoBook> bookshelf;

    /**
     * 构造（初始化添加书籍对话框界面）
     */
    public AddBookDialog() {
        initUI();
    }

    private void initUI() {
        // 使此窗口的大小适合其子组件的首选大小和布局
        this.pack();
        this.setSize(300, 300);
        // 设置窗口相对于指定组件的位置
        this.setLocationRelativeTo(null);

        // 卡片布局
        mainPanel = new JPanel(new CardLayout());
        mainPanel.setBounds(10, 10, 300, 300);

        // 初始化开始的卡片
        initStartCard();

        // 设置主面板
        this.setContentPane(mainPanel);
        // 指定对话框是否在显示时阻止输入到其他窗口
        this.setModal(true);
        this.setTitle("添加书籍");

        // 设置当用户在此对话框上启动“关闭”时默认发生的操作，dispose-window默认窗口关闭操作
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.setVisible(true);
    }

    /**
     * 初始化开始的卡片
     */
    private void initStartCard() {
        JPanel startCard = new JPanel();
        startCard.setBounds(0, 50, 300, 250);

        // 添加本地书籍 按钮
        JButton addLocalBookButton = new JButton("添加本地书籍");
        // 设置此组件的首选大小
        addLocalBookButton.setPreferredSize(new Dimension(200, 30));
        addLocalBookButton.addActionListener(e -> initLocalBookAddCard());
        startCard.add(addLocalBookButton);

        // 添加Legado书籍 按钮
        JButton addLegadoBookButton = new JButton("添加Legado书籍");
        // 设置此组件的首选大小
        addLegadoBookButton.setPreferredSize(new Dimension(200, 30));
        addLegadoBookButton.addActionListener(e -> initLegadoBookAddCard());
        startCard.add(addLegadoBookButton);

        mainPanel.add(startCard, "StartCard");
        // 展示开始卡片
        showCard("StartCard");
    }

    /**
     * 初始化本地书籍
     */
    private void initLocalBookAddCard() {
        // 本地书籍添加卡片
        JPanel localBookAddCard = new JPanel();
        localBookAddCard.setBounds(0, 50, 300, 250);

        // 文件系统地址浏览文本按钮，用于选择文件系统上的文件
        TextFieldWithBrowseButton filePath = new TextFieldWithBrowseButton();
        // 设置此组件的首选大小
        filePath.setPreferredSize(new Dimension(200, 30));
        filePath.addBrowseFolderListener("选择书籍", null, null, new FileChooserDescriptor(true, false, false, false, false, false));
        filePath.setEditable(false);
        localBookAddCard.add(filePath);

        // 书籍名称文本框
        JTextField name = new JTextField("书籍名");
        // 设置此组件的首选大小
        name.setPreferredSize(new Dimension(200, 30));
        localBookAddCard.add(name);

        // 作者 文本框
        JTextField author = new JTextField("作者");
        // 设置此组件的首选大小
        author.setPreferredSize(new Dimension(200, 30));
        localBookAddCard.add(author);

        // 生成目录 按钮
        JButton importButton = new JButton("生成目录");
        // 设置此组件的首选大小
        importButton.setPreferredSize(new Dimension(200, 30));
        // 添加监听主要是为了构造书籍对象
        importButton.addActionListener(e -> {
            String file = filePath.getText();
            // 文件地址必须存在且为txt文件
            if (StrUtil.isBlank(file) || !file.endsWith(".txt")) {
                AlertMessagesUtil.showInfoDialog("提示", "请选择正确的文件(必须为txt)");
                return;
            }
            Book book = new Book();
            book.setUrl(file);
            if (!"书籍名".equals(name.getText())) {
                book.setName(name.getText());
            }
            if (!"作者".equals(author.getText())) {
                book.setAuthor(author.getText());
            }
            book.setType(BookType.LOCAL);
            book.setChapterIndex(0);
            book.setCharset(CharsetUtils.charset(file));
            book.setChapterPattern(DEFAULT_CHAPTER_PATTERN);
            initDirectoryCard(book);
        });
        localBookAddCard.add(importButton);

        // 添加面板
        mainPanel.add(localBookAddCard, "LocalBookAddCard");

        // 展示本地书籍添加卡片
        showCard("LocalBookAddCard");
    }

    /**
     * 初始化Legado书籍添加卡片
     */
    private void initLegadoBookAddCard() {
        api = new LegadoApi(DataCache.readConfig.getLegadoHost());

        // 带加载的legado书架面板
        legadoBookAddCard = new JBLoadingPanel(new BorderLayout(), DataCache.project);

        // 书籍列表（禁止编辑）
        bookTable = new JBTable() {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        // 鼠标双击打开书籍
        bookTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    int row = bookTable.getSelectedRow();
                    LegadoBook book = bookshelf.get(row);
                    initDirectoryCard(book.toBook());
                }
            }
        });

        // 给legado书籍添加卡片添加滚动条
        legadoBookAddCard.add(new JBScrollPane(bookTable), BorderLayout.CENTER);
        getLegadoBookshelf();
        mainPanel.add(legadoBookAddCard, "LegadoBookAddCard");

        // 展示legado书籍添加卡片
        showCard("LegadoBookAddCard");
    }

    /**
     * 初始化目录卡片（这里展示生成目录时预览页）
     *
     * @param book 书籍信息
     */
    private void initDirectoryCard(Book book) {
        // 带加载的目录面板
        directoryCard = new JBLoadingPanel(new BorderLayout(), DataCache.project);
        // 滚动条
        JScrollPane scrollPane = new JBScrollPane();
        directoryCard.add(scrollPane, BorderLayout.CENTER);

        // 章节列表
        chapterList = new JBList<>();
        chapterList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        chapterList.setVisibleRowCount(8);
        scrollPane.setViewportView(chapterList);

        // 生成章节并设置至章节组件中
        getDirectory(book);

        // 本地书籍生成目录预览页
        if (book.getType() == BookType.LOCAL) {
            JPanel optPanel = new JPanel();
            JTextField chapterPatternJtf = new JTextField(15);
            chapterPatternJtf.setText(DEFAULT_CHAPTER_PATTERN);
            optPanel.add(chapterPatternJtf);
            // 重新生成目录按钮及相关事件
            JButton reGenerateJb = new JButton("重新生成");
            reGenerateJb.addActionListener(e -> {
                book.setChapterPattern(chapterPatternJtf.getText());
                getDirectory(book);
            });

            optPanel.add(reGenerateJb);
            directoryCard.add(optPanel, BorderLayout.NORTH);
        }
        // 保存
        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> {
            // 书籍章节非空
            if (CollUtil.isEmpty(chapters)) {
                AlertMessagesUtil.showWarningDialog("警告", "书籍章节目录为空");
                return;
            }
            // 设置书籍章节，并将书籍添加至书架
            book.setChapters(chapters);
            if (!DataCache.readConfig.addBook(book)) {
                AlertMessagesUtil.showInfoDialog("提示", "书籍已在书架中");
            }
            // 释放Window及其子组件及其所有子组件使用的所有本机屏幕资源
            this.dispose();
        });

        // 添加保存按钮
        directoryCard.add(saveButton, BorderLayout.SOUTH);

        mainPanel.add(directoryCard, "DirectoryCard");
        // 展示目录卡片
        showCard("DirectoryCard");
    }

    /**
     * 展示卡片
     *
     * @param card 卡片名称
     */
    private void showCard(String card) {
        CardLayout layout = (CardLayout) mainPanel.getLayout();
        // 使用 addLayoutComponent切换到使用指定的 name添加到此布局的组件
        layout.show(mainPanel, card);
    }

    /**
     * 生成章节并设置至章节组件中
     *
     * @param book 书籍信息
     */
    private void getDirectory(Book book) {
        // 开始加载
        directoryCard.startLoading();
        ThreadUtil.execute(() -> {
            try {
                // 章节列表并设置至组件中
                chapters = book.generateChapter();
                chapterList.setListData(chapters.toArray(Chapter[]::new));
            } catch (Exception e) {
                // 生成失败
                SwingUtilities.invokeLater(() -> {
                    AlertMessagesUtil.showWarningDialog("警告", "章节目录解析失败！");
                });
            } finally {
                // 结束加载
                directoryCard.stopLoading();
            }
        });
    }

    /**
     * 获取Legado书架
     */
    private void getLegadoBookshelf() {
        // 开始加载
        legadoBookAddCard.startLoading();
        ThreadUtil.execute(() -> {
            // 校验Legado地址
            if (!DataCache.readConfig.verifyLegadoHost()) {
                //　不通过，发出警告
                SwingUtilities.invokeLater(() -> {
                    AlertMessagesUtil.showWarningDialog("警告", "请先配置正确的Legado服务HOST");
                });
                showCard("StartCard");
                return;
            }
            try {
                // 通过，调用api获取书架
                bookshelf = api.getBookshelf();
                bookTable.setModel(TableDataUtil.legadoBookToTableModel(bookshelf));
            } catch (LegadoApiException e) {
                e.showErrorAlert();
            } finally {
                // 结束加载
                legadoBookAddCard.stopLoading();
            }
        });
    }
}
